home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / ip / nfs / nfswatch4.0 / screen.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-01  |  25.0 KB  |  1,056 lines

  1. #ifndef lint
  2. static char *RCSid = "$Header: /home/harbor/davy/system/nfswatch/RCS/screen.c,v 4.0 1993/03/01 19:59:00 davy Exp $";
  3. #endif
  4.  
  5. #include "os.h"
  6.  
  7. /*
  8.  * screen.c - routines for updating the screen.
  9.  *
  10.  * David A. Curry                Jeffrey C. Mogul
  11.  * Purdue University                Digital Equipment Corporation
  12.  * Engineering Computer Network            Western Research Laboratory
  13.  * 1285 Electrical Engineering Building        250 University Avenue
  14.  * West Lafayette, IN 47907-1285        Palo Alto, CA 94301
  15.  * davy@ecn.purdue.edu                mogul@decwrl.dec.com
  16.  *
  17.  * $Log: screen.c,v $
  18.  * Revision 4.0  1993/03/01  19:59:00  davy
  19.  * NFSWATCH Version 4.0.
  20.  *
  21.  * Revision 3.8  1993/02/24  17:44:45  davy
  22.  * Added -auth mode, changes to -proc mode, -map option, -server option.
  23.  *
  24.  * Revision 3.7  1993/01/18  19:35:16  davy
  25.  * Small patch from Jeff.
  26.  *
  27.  * Revision 3.6  1993/01/16  19:08:59  davy
  28.  * Corrected Jeff's address.
  29.  *
  30.  * Revision 3.5  1993/01/15  19:33:39  davy
  31.  * Miscellaneous cleanups.
  32.  *
  33.  * Revision 3.4  1993/01/15  15:43:36  davy
  34.  * Assorted changes for porting to Solaris 2.x/SVR4.
  35.  *
  36.  * Revision 3.3  1993/01/13  21:25:31  davy
  37.  * Stupid portability change for IRIX.
  38.  *
  39.  * Revision 3.2  1993/01/13  20:18:17  davy
  40.  * Put in OS-specific define scheme, and merged in Tim Hudson's code for
  41.  * SGI systems (as yet untested).
  42.  *
  43.  * Revision 3.1  1993/01/13  14:35:44  davy
  44.  * Added "n" command to toggle displaying host names/numbers.
  45.  *
  46.  * Revision 3.0  1991/01/23  08:23:23  davy
  47.  * NFSWATCH Version 3.0.
  48.  *
  49.  * Revision 1.4  91/01/17  10:13:30  davy
  50.  * New features from Jeff Mogul.
  51.  * 
  52.  * Revision 1.7  91/01/16  15:49:41  mogul
  53.  * Make sure snapshot captures up-to-date screen.
  54.  * 
  55.  * Revision 1.6  91/01/07  14:24:05  mogul
  56.  * fixed a few little bugs
  57.  * 
  58.  * Revision 1.5  91/01/07  14:10:43  mogul
  59.  * Added scrolling
  60.  * Added help screen
  61.  * 
  62.  * Revision 1.4  91/01/04  14:13:29  mogul
  63.  * Support for client counters
  64.  * disable screen update during database upheaval
  65.  * indicate how many files/file systems/procedures/clients not shown
  66.  * 
  67.  * Revision 1.3  91/01/03  17:42:16  mogul
  68.  * Support for per-procedure counters
  69.  * 
  70.  * Revision 1.2  90/08/17  15:47:48  davy
  71.  * NFSWATCH Version 2.0.
  72.  * 
  73.  * Revision 1.1  88/11/29  11:21:03  davy
  74.  * NFSWATCH Release 1.0
  75.  * 
  76.  */
  77. #include <sys/param.h>
  78. #include <sys/time.h>
  79. #include <netinet/in.h>
  80. #include <curses.h>
  81. #include <stdio.h>
  82. #include <signal.h>
  83. #include <math.h>
  84.  
  85. #include "nfswatch.h"
  86. #include "externs.h"
  87. #include "screen.h"
  88.  
  89. /*
  90.  * Screen text items which are always displayed.
  91.  */
  92. static struct scrtxt scrtxts[] = {
  93.     SCR_HOST_X,    SCR_HOST_Y,    dsthost,
  94.     SCR_ELAPS_X0,    SCR_ELAPS_Y,    "Elapsed time:",
  95.     SCR_ELAPS_X,    SCR_ELAPS_Y,    "00:00:00",
  96.     SCR_PKTINT_X0,    SCR_PKTINT_Y,    "Interval packets:",
  97.     SCR_PKTTOT_X0,    SCR_PKTTOT_Y,    "Total packets:",
  98.     SCR_PKTHDR_X,    SCR_PKTHDR_Y,    "int   pct   total",
  99.     SCR_PKTHDR_X+SCR_MIDDLE,    SCR_PKTHDR_Y,
  100.                     "int   pct   total",
  101.     -1,        -1,        NULL
  102. };
  103.  
  104. /*
  105.  * Screen text items displayed when showing file systems
  106.  * (showwhich == SHOWFILESYSTEM).
  107.  */
  108. static struct scrtxt fstxts[] = {
  109.     SCR_NFSHDR_X,    SCR_NFSHDR_Y,    "File Sys        int   pct   total",
  110.     SCR_NFSHDR_X+SCR_MIDDLE,    SCR_NFSHDR_Y,
  111.                     "File Sys        int   pct   total",
  112.     -1,        -1,        NULL
  113. };
  114.  
  115. /*
  116.  * Screen text items displayed when showing individual files
  117.  * (showwhich == SHOWINDVFILES).
  118.  */
  119. static struct scrtxt fitxts[] = {
  120.     SCR_NFSHDR_X,    SCR_NFSHDR_Y,    "File            int   pct   total",
  121.     SCR_NFSHDR_X+SCR_MIDDLE,    SCR_NFSHDR_Y,
  122.                     "File            int   pct   total",
  123.     -1,        -1,        NULL
  124. };
  125.  
  126. /*
  127.  * Screen text items displayed when showing individual procedures
  128.  * (showwhich == SHOWNFSPROCS).
  129.  */
  130. static struct scrtxt prtxts[] = {
  131.     0,        SCR_NFSHDR_Y,
  132.         " Procedure           int   pct   total  completed  ave.resp  var.resp  max.resp",
  133.     -1,        -1,        NULL
  134. };
  135.  
  136. /*
  137.  * Screen text items displayed when showing individual clients
  138.  * (showwhich == SHOWCLIENTS).
  139.  */
  140. static struct scrtxt cltxts[] = {
  141.     0,        SCR_NFSHDR_Y,
  142.         "Client host          int   pct   total",
  143.     SCR_MIDDLE,    SCR_NFSHDR_Y,
  144.         "Client host          int   pct   total",
  145.     -1,        -1,        NULL
  146. };
  147.  
  148. /*
  149.  * Screen text items displayed when showing individual authenticators
  150.  * (showwhich == SHOWAUTH).
  151.  */
  152. static struct scrtxt actxts[] = {
  153.     0,        SCR_NFSHDR_Y,
  154.         "Authenticator        int   pct   total",
  155.     SCR_MIDDLE,    SCR_NFSHDR_Y,
  156.         "Authenticator        int   pct   total",
  157.     -1,        -1,        NULL
  158. };
  159.  
  160. /*
  161.  * Screen text items for help page (showwhich == SHOWHELP).
  162.  */
  163. #define    SCR_HELPHDR_Y (SCR_NFSHDR_Y - 1)
  164. static struct scrtxt helptxts[] = {
  165.     2,        SCR_HELPHDR_Y+0, "^L\tRedraw screen",
  166.     3,        SCR_HELPHDR_Y+1, "a\tDisplay RPC authentication",
  167.     3,        SCR_HELPHDR_Y+2, "c\tDisplay NFS client hosts",
  168.     3,        SCR_HELPHDR_Y+3, "f\tDisplay file systems",
  169.     3,        SCR_HELPHDR_Y+4, "l\tToggle logging",
  170.     3,        SCR_HELPHDR_Y+5, "n\tToggle host numbers/names",
  171.     3,        SCR_HELPHDR_Y+6, "p\tDisplay NFS procedures",
  172.     3,        SCR_HELPHDR_Y+7, "q\tQuit",
  173.     3,        SCR_HELPHDR_Y+8, "s\tWrite snapshot",
  174.  
  175.     SCR_MIDDLE+3,    SCR_HELPHDR_Y+0, "u\tToggle sort by % usage",
  176.     SCR_MIDDLE+3,    SCR_HELPHDR_Y+1, ">\tIncrease cycle time by one sec",
  177.     SCR_MIDDLE+3,    SCR_HELPHDR_Y+2, "<\tDecrease cycle time by one sec",
  178.     SCR_MIDDLE+3,    SCR_HELPHDR_Y+3, "+\tIncrease cycle time by 10 secs",
  179.     SCR_MIDDLE+3,    SCR_HELPHDR_Y+4, "-\tDecrease cycle time by 10 secs",
  180.     SCR_MIDDLE+3,    SCR_HELPHDR_Y+5, "=\tReset cycle time to 10 secs",
  181.     SCR_MIDDLE+3,    SCR_HELPHDR_Y+6, "]\tScroll forward",
  182.     SCR_MIDDLE+3,    SCR_HELPHDR_Y+7, "[\tScroll back",
  183.     SCR_MIDDLE,    SCR_HELPHDR_Y+8, " \t*space bar resumes display*",
  184.  
  185.     SCR_MIDDLE - 6,    SCR_HELPHDR_Y+9, "--COMMANDS--",
  186.  
  187.     -1,        -1,        NULL
  188. };
  189.  
  190. static int showbyname = 1;    /* show host names/numbers    */
  191.  
  192. static int prev_showwhich = 0;    /* used for resuming after help */
  193.  
  194. /*
  195.  * scrolling offsets, one for each display type, in terms of displayed
  196.  * items (i.e., lines skipped * 2)
  197.  */
  198. static int scroll_off[SHOW_MAXCODE+1];
  199.  
  200. /*
  201.  * This array tells the scrolling mechanism how far a display can be scrolled;
  202.  *    NULL entries are not scrollable.
  203.  */
  204. static int maxnfsproc = MAXNFSPROC;
  205. static int *scroll_limit[SHOW_MAXCODE+1] = {
  206.         NULL,
  207.         &nfilecounters, &nnfscounters, &maxnfsproc, &nclientcounters,
  208.         &nauthcounters, NULL
  209. };
  210.  
  211. /*
  212.  * setup_screen - initialize the display screen.
  213.  */
  214. void
  215. setup_screen(device)
  216. char *device;
  217. {
  218.     int len;
  219.     char *tstr;
  220.     char *ctime();
  221.     register int i;
  222.     char buf[BUFSIZ];
  223.     struct timeval tv;
  224.     register struct scrtxt *st;
  225.  
  226. #ifdef ultrix
  227.     struct winsize ws;
  228.  
  229.     /*
  230.      * Get around the old version of curses Ultrix has.
  231.      * -lcursesX would probably do this as well.
  232.      */
  233.     if (ioctl(2, TIOCGWINSZ, &ws) >= 0)
  234.         LINES = ws.ws_row;
  235. #endif
  236.  
  237.     /*
  238.      * Initialize the screen.
  239.      */
  240.     (void) initscr();
  241.     screen_inited = 1;
  242.  
  243.     /*
  244.      * Turn echo off, cbreak on.
  245.      */
  246.     (void) noecho();
  247.  
  248. #ifdef crmode
  249.     (void) crmode();
  250. #else
  251.     (void) cbreak();
  252. #endif
  253.  
  254.     /*
  255.      * Clear the screen.
  256.      */
  257.     (void) clear();
  258.  
  259.     /*
  260.      * Get the time of day.
  261.       */
  262.     (void) gettimeofday(&tv, 0);
  263.     tstr = ctime(&tv.tv_sec);
  264.  
  265.     (void) mvprintw(SCR_DATE_Y, SCR_DATE_X, "%.24s", tstr);
  266.  
  267.     /*
  268.      * Now draw the various strings on the screen.
  269.      */
  270.     for (st = scrtxts; st->s_text != NULL; st++)
  271.         (void) mvprintw(st->s_y, st->s_x, "%s", st->s_text);
  272.  
  273.     if (allintf)
  274.         (void) sprintf(buf, "Monitoring packets from all interfaces");
  275.     else
  276.         (void) sprintf(buf, "Monitoring packets from interface %s",
  277.                    device);
  278.  
  279.     len = strlen(buf);
  280.  
  281.     (void) mvprintw(SCR_IF_Y, SCR_MIDDLE - (len/2), buf);
  282.     (void) mvprintw(SCR_PROMPT_Y, SCR_PROMPT_X0, prompt);
  283. }
  284.  
  285. /*
  286.  * label_screen - put all packet counter labels on screen.
  287.  */
  288. void
  289. label_screen()
  290. {
  291.     register int i;
  292.     register struct scrtxt *st;
  293.     register int soff = scroll_off[showwhich];
  294.  
  295.     /*
  296.      * Display packet counter labels.
  297.      */
  298.     for (i = 0; i < PKT_NCOUNTERS; i++) {
  299.         (void) mvprintw(pkt_counters[i].pc_namey,
  300.             pkt_counters[i].pc_namex, "%.*s",
  301.             SCR_PKTLEN, pkt_counters[i].pc_name);
  302.     }
  303.  
  304.     /*
  305.      * Clear NFS packet counter lines, since we may be
  306.      * changing them.
  307.      */
  308.     for (i = SCR_NFSHDR_Y; i < (LINES - 1); i++) {
  309.         (void) move(i, 0);
  310.         (void) clrtoeol();
  311.     }
  312.  
  313.     /*
  314.      * Display the labels for the NFS packet counter lines.
  315.      */
  316.     if (showwhich == SHOWFILESYSTEM) {
  317.         for (st = fstxts; st->s_text != NULL; st++)
  318.             (void) mvprintw(st->s_y, st->s_x, "%s", st->s_text);
  319.  
  320.         for (i = soff;
  321.             (i < nnfscounters) && ((i - soff) < NFSLINES); i++) {
  322.             (void) mvprintw(nfs_counters[i - soff].nc_namey,
  323.                 nfs_counters[i - soff].nc_namex, "%.*s",
  324.                 SCR_NFSLEN, nfs_counters[i].nc_name);
  325.         }
  326.     }
  327.     else if (showwhich == SHOWNFSPROCS) {
  328.         for (st = prtxts; st->s_text != NULL; st++)
  329.             (void) mvprintw(st->s_y, st->s_x, "%s", st->s_text);
  330.  
  331.         for (i = soff;
  332.             (i < MAXNFSPROC) && ((i - soff) < NFSLINES); i++) {
  333.             (void) mvprintw(prc_counters[i - soff].pr_namey,
  334.                     prc_counters[i - soff].pr_namex,
  335.                     "%.*s", SCR_NFSLEN,
  336.                     prc_counters[i].pr_name);
  337.         }
  338.     }
  339.     else if (showwhich == SHOWCLIENTS) {
  340.         for (st = cltxts; st->s_text != NULL; st++)
  341.             (void) mvprintw(st->s_y, st->s_x, "%s", st->s_text);
  342.  
  343.         for (i = soff; 
  344.               (i < nclientcounters) && ((i - soff) < NFSLINES); i++) {
  345.             if (showbyname) {
  346.                 (void) mvprintw(clnt_counters[i - soff].cl_namey,
  347.                     clnt_counters[i - soff].cl_namex,
  348.                     "%.*s", SCR_NFSLEN,
  349.                     clnt_counters[i].cl_name);
  350.             }
  351.             else {
  352.                 struct in_addr tmp;
  353.  
  354.                 bcopy(&clnt_counters[i].cl_ipaddr, &tmp, sizeof(long));
  355.                 (void) mvprintw(clnt_counters[i - soff].cl_namey,
  356.                     clnt_counters[i - soff].cl_namex,
  357.                     "%.*s", SCR_NFSLEN,
  358.                     inet_ntoa(tmp));
  359.             }
  360.         }
  361.     }
  362.     else if (showwhich == SHOWAUTH) {
  363.         for (st = actxts; st->s_text != NULL; st++)
  364.             (void) mvprintw(st->s_y, st->s_x, "%s", st->s_text);
  365.  
  366.         for (i = soff;
  367.              (i < nauthcounters) && ((i - soff) < NFSLINES); i++) {
  368.             (void) mvprintw(auth_counters[i - soff].ac_namey,
  369.                     auth_counters[i - soff].ac_namex,
  370.                     "%.*s", SCR_NFSLEN,
  371.                     auth_counters[i].ac_name);
  372.         }
  373.     }
  374.     else if (showwhich == SHOWHELP) {
  375.         /* We "stole" one line so we must clear it */
  376.         (void) move(SCR_HELPHDR_Y, 0);
  377.         (void) clrtoeol();
  378.  
  379.         for (st = helptxts; st->s_text != NULL; st++)
  380.             (void) mvprintw(st->s_y, st->s_x, "%s", st->s_text);
  381.     }
  382.     else {
  383.         for (st = fitxts; st->s_text != NULL; st++)
  384.             (void) mvprintw(st->s_y, st->s_x, "%s", st->s_text);
  385.  
  386.         for (i = soff;
  387.             (i < nfilecounters) && ((i - soff) < NFSLINES); i++) {
  388.             (void) mvprintw(fil_counters[i - soff].fc_namey,
  389.                 fil_counters[i - soff].fc_namex, "%.*s",
  390.                 SCR_NFSLEN, fil_counters[i].fc_name);
  391.         }
  392.     }
  393. }
  394.  
  395. /*
  396.  * update_screen - update the screen with new information.
  397.  */
  398. void
  399. update_screen()
  400. {
  401.     char *tstr;
  402.     char *ctime();
  403.     float percent;
  404.     struct timeval tv;
  405.     register int i, nfstotal;
  406.     register int soff = scroll_off[showwhich];
  407.  
  408.     (void) gettimeofday(&tv, (struct timezone *) 0);
  409.  
  410.     (void) mvprintw(SCR_DATE_Y, SCR_DATE_X, "%.24s", ctime(&tv.tv_sec));
  411.  
  412.     tv.tv_sec -= starttime.tv_sec;
  413.     tstr = prtime(tv.tv_sec);
  414.  
  415.     /*
  416.      * Print the headers.
  417.      */
  418.     (void) mvprintw(SCR_ELAPS_Y, SCR_ELAPS_X, "%.8s", tstr);
  419.     (void) mvprintw(SCR_PKTINT_Y, SCR_PKTINT_X,
  420.         "%8d (network)   %8d (to host)   %8d (dropped)",
  421.         int_pkt_total, int_dst_pkt_total, int_pkt_drops);
  422.     (void) mvprintw(SCR_PKTTOT_Y, SCR_PKTTOT_X,
  423.         "%8d (network)   %8d (to host)   %8d (dropped)",
  424.         pkt_total, dst_pkt_total, pkt_drops);
  425.  
  426.     /*
  427.      * Print the packet counters.  Percentage is calculated as
  428.      * this interval counter over total packets this interval.
  429.      */
  430.     for (i = 0; i < PKT_NCOUNTERS; i++) {
  431.         if (int_dst_pkt_total) {
  432.             percent = ((float) pkt_counters[i].pc_interval /
  433.                   (float) int_dst_pkt_total) * 100.0;
  434.         }
  435.         else {
  436.             percent = 0.0;
  437.         }
  438.  
  439.         (void) mvprintw(pkt_counters[i].pc_inty,
  440.             pkt_counters[i].pc_intx, "%5d",
  441.             pkt_counters[i].pc_interval);
  442.  
  443.         (void) mvprintw(pkt_counters[i].pc_pcty,
  444.             pkt_counters[i].pc_pctx, "%3.0f%%",
  445.             percent);
  446.  
  447.         (void) mvprintw(pkt_counters[i].pc_toty,
  448.             pkt_counters[i].pc_totx, "%8d",
  449.             pkt_counters[i].pc_total);
  450.     }
  451.  
  452.     /*
  453.      * Calculate the total number of NFS packets this
  454.      * interval.
  455.      */
  456.     nfstotal = pkt_counters[PKT_NFSWRITE].pc_interval +
  457.            pkt_counters[PKT_NFSREAD].pc_interval;
  458.  
  459.     if (showwhich == SHOWFILESYSTEM) {
  460.         /*
  461.          * Print the NFS counters.  Percentage is calculated as
  462.          * packets this interval over total NFS packets this
  463.          * interval.
  464.          */
  465.         HowMany("file systems", nnfscounters);
  466.  
  467.         for (i = soff;
  468.             (i < nnfscounters) && ((i - soff) < NFSLINES); i++) {
  469.             if (nfstotal) {
  470.                 percent = ((float) nfs_counters[i].nc_interval /
  471.                       (float) nfstotal) * 100.0;
  472.             }
  473.             else {
  474.                 percent = 0.0;
  475.             }
  476.  
  477.             (void) mvprintw(nfs_counters[i - soff].nc_inty,
  478.                 nfs_counters[i - soff].nc_intx, "%5d",
  479.                 nfs_counters[i].nc_interval);
  480.  
  481.             (void) mvprintw(nfs_counters[i - soff].nc_pcty,
  482.                 nfs_counters[i - soff].nc_pctx, "%3.0f%%",
  483.                 percent);
  484.  
  485.             (void) mvprintw(nfs_counters[i - soff].nc_toty,
  486.                 nfs_counters[i - soff].nc_totx, "%8d",
  487.                 nfs_counters[i].nc_total);
  488.         }
  489.     }
  490.     else if (showwhich == SHOWNFSPROCS) {
  491.         long count, tot_count;
  492.         double dcount, sumsqr, sum;
  493.  
  494.         tot_count = 0;
  495.  
  496.         /* Sum up all over all the procedures  */
  497.         for (i = 0; i < MAXNFSPROC; i++) {
  498.             tot_count += prc_counters[i].pr_interval;
  499.         }
  500.  
  501.         HowMany("NFS Procedures", MAXNFSPROC);
  502.  
  503.         for (i = soff;
  504.             (i < MAXNFSPROC) && ((i - soff) < NFSLINES); i++) {
  505.             if (tot_count)
  506.             percent = (((float) prc_counters[i].pr_interval)
  507.                      / ((float)tot_count)) * 100.0;
  508.             else
  509.             percent = 0.0;
  510.  
  511.             (void) mvprintw(prc_counters[i - soff].pr_inty,
  512.                 prc_counters[i - soff].pr_intx, "%5d",
  513.                 prc_counters[i].pr_interval);
  514.  
  515.             (void) mvprintw(prc_counters[i - soff].pr_pcty,
  516.                 prc_counters[i - soff].pr_pctx, "%3.0f%%",
  517.                 percent);
  518.  
  519.             (void) mvprintw(prc_counters[i - soff].pr_toty,
  520.                 prc_counters[i - soff].pr_totx, "%8d",
  521.                 prc_counters[i].pr_total);
  522.  
  523.             count = prc_counters[i].pr_complete;
  524.  
  525.             if (count != 0) {
  526.             dcount = (double) count;
  527.             sum = prc_counters[i].pr_response;
  528.             sumsqr = prc_counters[i].pr_respsqr;
  529.  
  530.             (void) mvprintw(prc_counters[i - soff].pr_rmaxy,
  531.                     prc_counters[i - soff].pr_rmaxx,
  532.                     "%8.2f",
  533.                     prc_counters[i].pr_maxresp);
  534.  
  535.             (void) mvprintw(prc_counters[i - soff].pr_compy,
  536.                     prc_counters[i - soff].pr_compx,
  537.                     "%8d",
  538.                     count);
  539.  
  540.             (void) mvprintw(prc_counters[i - soff].pr_respy,
  541.                     prc_counters[i - soff].pr_respx,
  542.                     "%8.2f",
  543.                     sum / dcount);
  544.  
  545.             if (count > 1) {
  546.                 (void) mvprintw(prc_counters[i - soff].pr_rsqry,
  547.                         prc_counters[i - soff].pr_rsqrx,
  548.                         "%8.2f",
  549.                         sqrt((dcount * sumsqr - sum * sum) /
  550.                              (dcount * (dcount - 1.0))));
  551.             }
  552.             }
  553.         }
  554.     }
  555.     else if (showwhich == SHOWCLIENTS) {
  556.         long tot_count;
  557.  
  558.         tot_count = 0;
  559.  
  560.         /* Sum up all over all the clients  */
  561.         for (i = 0; i < nclientcounters; i++) {
  562.             tot_count += clnt_counters[i].cl_interval;
  563.         }
  564.  
  565.         HowMany("client hosts", nclientcounters);
  566.  
  567.         for (i = soff;
  568.              (i < nclientcounters) && ((i - soff) < NFSLINES); i++) {
  569.             if (tot_count)
  570.             percent = (((float) clnt_counters[i].cl_interval)
  571.                      / ((float)tot_count)) * 100.0;
  572.             else
  573.             percent = 0.0;
  574.  
  575.             (void) mvprintw(clnt_counters[i - soff].cl_inty,
  576.                 clnt_counters[i - soff].cl_intx, "%5d",
  577.                 clnt_counters[i].cl_interval);
  578.  
  579.             (void) mvprintw(clnt_counters[i - soff].cl_pcty,
  580.                 clnt_counters[i - soff].cl_pctx, "%3.0f%%",
  581.                 percent);
  582.  
  583.             (void) mvprintw(clnt_counters[i - soff].cl_toty,
  584.                 clnt_counters[i - soff].cl_totx, "%8d",
  585.                 clnt_counters[i].cl_total);
  586.         }
  587.     }
  588.     else if (showwhich == SHOWAUTH) {
  589.         long tot_count;
  590.  
  591.         tot_count = 0;
  592.  
  593.         /*
  594.          * Sum up over all the authenticators.
  595.          */
  596.         for (i=0; i < nauthcounters; i++) {
  597.             tot_count += auth_counters[i].ac_interval;
  598.         }
  599.  
  600.         HowMany("authenticators", nauthcounters);
  601.  
  602.         for (i = soff;
  603.              (i < nauthcounters) && ((i - soff) < NFSLINES); i++) {
  604.             if (tot_count)
  605.                 percent = (((float) auth_counters[i].ac_interval)
  606.                        / ((float) tot_count)) * 100.0;
  607.             else
  608.                 percent = 0.0;
  609.  
  610.             (void) mvprintw(auth_counters[i - soff].ac_inty,
  611.                     auth_counters[i - soff].ac_intx,
  612.                     "%5d",
  613.                     auth_counters[i].ac_interval);
  614.  
  615.             (void) mvprintw(auth_counters[i - soff].ac_pcty,
  616.                     auth_counters[i - soff].ac_pctx,
  617.                     "%3.0f%%",
  618.                     percent);
  619.  
  620.             (void) mvprintw(auth_counters[i - soff].ac_toty,
  621.                     auth_counters[i - soff].ac_totx,
  622.                     "%8d",
  623.                     auth_counters[i].ac_total);
  624.         }
  625.     }
  626.     else if (showwhich == SHOWHELP) {
  627.         /* do nothing */
  628.     }
  629.     else {
  630.         /*
  631.          * Print the file counters.  Percentage is calculated as
  632.          * packets this interval over total NFS packets this
  633.          * interval.
  634.          */
  635.         HowMany("files", nfilecounters);
  636.  
  637.         for (i = soff;
  638.             (i < nfilecounters) && ((i - soff) < NFSLINES); i++) {
  639.             if (nfstotal) {
  640.                 percent = ((float) fil_counters[i].fc_interval /
  641.                       (float) nfstotal) * 100.0;
  642.             }
  643.             else {
  644.                 percent = 0.0;
  645.             }
  646.  
  647.             (void) mvprintw(fil_counters[i - soff].fc_inty,
  648.                 fil_counters[i - soff].fc_intx, "%5d",
  649.                 fil_counters[i].fc_interval);
  650.  
  651.             (void) mvprintw(fil_counters[i - soff].fc_pcty,
  652.                 fil_counters[i - soff].fc_pctx, "%3.0f%%",
  653.                 percent);
  654.  
  655.             (void) mvprintw(fil_counters[i - soff].fc_toty,
  656.                 fil_counters[i - soff].fc_totx, "%8d",
  657.                 fil_counters[i].fc_total);
  658.         }
  659.     }
  660.  
  661.     (void) move(SCR_PROMPT_Y, SCR_PROMPT_X);
  662.     (void) clrtoeol();
  663.     (void) refresh();
  664. }
  665.  
  666. /*
  667.  * HowMany - put up a label showing how many XXs known/not displayed
  668.  */
  669. HowMany(legend, number)
  670. char *legend;
  671. int number;
  672. {
  673.     static char message[80];
  674.     int mlen;
  675.     
  676.     if (number > NFSLINES) {
  677.         sprintf(message, "%d %s [%d not displayed]", number, legend,
  678.             number - NFSLINES);
  679.     }
  680.     else
  681.         sprintf(message, "%d %s", number, legend);
  682.  
  683.     mlen = strlen(message);
  684.     (void)move(SCR_NFSHDR_Y - 1, 0);
  685.     (void)clrtoeol();
  686.     (void)mvprintw(SCR_NFSHDR_Y - 1, SCR_MIDDLE - (mlen/2), message);
  687.     
  688.     /*
  689.      * Display scrolling information
  690.      */
  691.     if (scroll_off[showwhich] > 0)
  692.         (void)mvprintw(SCR_NFSHDR_Y - 1, 2, "<-more");
  693.     if (scroll_limit[showwhich]) {
  694.         int slim = *scroll_limit[showwhich];
  695.         if ((scroll_off[showwhich] + NFSLINES) < slim)
  696.         (void)mvprintw(SCR_NFSHDR_Y - 1, 
  697.                 (SCR_MIDDLE * 2) - 8, "more->");
  698.     }
  699. }
  700.  
  701.  
  702. /*
  703.  * command - process a command.
  704.  */
  705. void
  706. command()
  707. {
  708.     register int c;
  709.     struct itimerval itv;
  710.     int oldm;
  711.     int reset_prevshowwhich = 1;
  712.  
  713.     if ((c = getchar()) == EOF)
  714.         finish(-1);
  715.  
  716.     c &= 0177;
  717.  
  718.     switch (c) {
  719.     case '\014':            /* redraw            */
  720.         (void) clearok(curscr, TRUE);
  721.         (void) refresh();
  722.         reset_prevshowwhich = 0;
  723.         break;
  724.     case 'a':            /* show RPC authentication    */
  725.     case 'A':
  726.         showwhich = SHOWAUTH;
  727.         (void) mvprintw(SCR_PROMPT_Y, SCR_PROMPT_X,
  728.                 "display RPC authenticators (starting next update)");
  729.  
  730.         (void) clrtoeol();
  731.         (void) refresh();
  732.  
  733.         /*
  734.          * Change screen labels.
  735.          */
  736.         label_screen();
  737.         break;
  738.     case 'c':            /* show NFS clients        */
  739.     case 'C':
  740.         showwhich = SHOWCLIENTS;
  741.         (void) mvprintw(SCR_PROMPT_Y, SCR_PROMPT_X,
  742.             "display NFS clients (starting next update)");
  743.  
  744.         (void) clrtoeol();
  745.         (void) refresh();
  746.  
  747.         /*
  748.          * Change screen labels.
  749.          */
  750.         label_screen();
  751.         break;
  752.     case 'f':            /* toggle what we show        */
  753.     case 'F':
  754.         switch (showwhich) {
  755.         case SHOWFILESYSTEM:
  756.             /*
  757.              * Only do this if it makes sense.
  758.              */
  759.             if (filelist == NULL)
  760.             break;
  761.             showwhich = SHOWINDVFILES;
  762.             break;
  763.         case SHOWINDVFILES:
  764.             showwhich = SHOWFILESYSTEM;
  765.             break;
  766.         case SHOWNFSPROCS:
  767.         case SHOWCLIENTS:
  768.         case SHOWHELP:
  769.             showwhich = SHOWFILESYSTEM;
  770.             break;
  771.         }
  772.  
  773.         (void) mvprintw(SCR_PROMPT_Y, SCR_PROMPT_X,
  774.             "display %s (starting next update)",
  775.                 (showwhich == SHOWFILESYSTEM ?
  776.                 "file systems" : "individual files"));
  777.  
  778.         (void) clrtoeol();
  779.         (void) refresh();
  780.  
  781.         /*
  782.          * Change screen labels.
  783.          */
  784.         label_screen();
  785.         break;
  786.     case 'l':            /* toggle logging        */
  787.     case 'L':
  788.         reset_prevshowwhich = 0;
  789.         if (logging) {
  790.             (void) mvprintw(SCR_PROMPT_Y, SCR_PROMPT_X,
  791.                 "logging turned off");
  792.  
  793.             (void) fprintf(logfp, "#\n# endlog\n#\n");
  794.             (void) fclose(logfp);
  795.             logging = 0;
  796.         }
  797.         else {
  798.             if ((logfp = fopen(logfile, "a")) == NULL) {
  799.                 (void) mvprintw(SCR_PROMPT_Y, SCR_PROMPT_X,
  800.                     "could not open \"%s\"", logfile);
  801.             }
  802.             else {
  803.                 (void) mvprintw(SCR_PROMPT_Y, SCR_PROMPT_X,
  804.                     "logging to \"%s\"", logfile);
  805.  
  806.                 (void) fprintf(logfp, "#\n# startlog\n#\n");
  807.                 (void) fprintf(logfp, "# NFSwatch log file\n");
  808.                 (void) fprintf(logfp, "#    Packets from: %s\n",
  809.                     (srcflag ? srchost : "all hosts"));
  810.                 (void) fprintf(logfp, "#    Packets to:   %s\n#\n",
  811.                     dsthost);
  812.  
  813.                 logging = 1;
  814.             }
  815.         }
  816.  
  817.         (void) clrtoeol();
  818.         (void) refresh();
  819.         break;
  820.     case 'n':            /* show numbers/names        */
  821.     case 'N':
  822.         showbyname = (!showbyname);
  823.  
  824.         (void) mvprintw(SCR_PROMPT_Y, SCR_PROMPT_X,
  825.                 "show host %s (starting next update)",
  826.                 showbyname ? "names" : "numbers");
  827.  
  828.         (void) clrtoeol();
  829.         (void) refresh();
  830.  
  831.         /*
  832.          * Change screen labels.
  833.          */
  834.         label_screen();
  835.         break;
  836.     case 'p':            /* show NFS procedures        */
  837.     case 'P':
  838.         showwhich = SHOWNFSPROCS;
  839.         (void) mvprintw(SCR_PROMPT_Y, SCR_PROMPT_X,
  840.             "display NFS procedures (starting next update)");
  841.  
  842.         (void) clrtoeol();
  843.         (void) refresh();
  844.  
  845.         /*
  846.          * Change screen labels.
  847.          */
  848.         label_screen();
  849.         break;
  850.     case 'q':            /* quit                */
  851.     case 'Q':
  852.         (void) mvaddch(SCR_PROMPT_Y, SCR_PROMPT_X, c);
  853.         (void) refresh();
  854.         finish(-1);
  855.         break;
  856.     case 's':            /* snapshot            */
  857.     case 'S':
  858.         reset_prevshowwhich = 0;
  859. #ifdef SVR4
  860.         sighold(SIGALRM);
  861. #else
  862.         oldm = sigblock(sigmask(SIGALRM));
  863. #endif
  864.                         /* no async redisplay while dumping */
  865.         snapshot();
  866. #ifdef SVR4
  867.         sigrelse(SIGALRM);
  868. #else
  869.         (void) sigsetmask(oldm);    /* permit async redisplay */
  870. #endif
  871.         break;
  872.     case 'u':            /* toggle sort method        */
  873.     case 'U':
  874.         reset_prevshowwhich = 0;
  875.         sortbyusage = (!sortbyusage);
  876.  
  877.         (void) mvprintw(SCR_PROMPT_Y, SCR_PROMPT_X,
  878.                 "sort by %s (starting next update)",
  879.                 sortbyusage ? "percent usage" : "name");
  880.  
  881.         (void) clrtoeol();
  882.         (void) refresh();
  883.  
  884.         /*
  885.          * Change the sort order now.
  886.          */
  887. #ifdef SVR4
  888.         sighold(SIGALRM);
  889. #else
  890.         oldm = sigblock(sigmask(SIGALRM));
  891. #endif
  892.                         /* no redisplay while unstable */
  893.         sort_nfs_counters();
  894.         sort_prc_counters();
  895.         sort_clnt_counters();
  896.         sort_auth_counters();
  897. #ifdef SVR4
  898.         sigrelse(SIGALRM);
  899. #else
  900.         (void) sigsetmask(oldm);    /* permit redisplay */
  901. #endif
  902.  
  903.         /*
  904.          * Update screen labels and values.
  905.          */
  906.         label_screen();
  907.         update_screen();
  908.         break;
  909.     case '>':            /* add 1 to cycle time        */
  910.         reset_prevshowwhich = 0;
  911.         cycletime++;
  912.  
  913.         (void) getitimer(ITIMER_REAL, &itv);
  914.  
  915.         itv.it_interval.tv_sec = cycletime;
  916.         itv.it_interval.tv_usec = 0;
  917.  
  918.         (void) setitimer(ITIMER_REAL, &itv, (struct itimerval *) 0);
  919.  
  920.         (void) mvprintw(SCR_PROMPT_Y, SCR_PROMPT_X,
  921.             "cycletime = %d seconds", cycletime);
  922.         (void) clrtoeol();
  923.         (void) refresh();
  924.         break;
  925.     case '<':            /* subtract 1 from cycletime    */
  926.         reset_prevshowwhich = 0;
  927.         if (cycletime > 1) {
  928.             cycletime--;
  929.  
  930.             (void) getitimer(ITIMER_REAL, &itv);
  931.  
  932.             itv.it_interval.tv_sec = cycletime;
  933.             itv.it_interval.tv_usec = 0;
  934.  
  935.             (void) setitimer(ITIMER_REAL, &itv,
  936.                 (struct itimerval *) 0);
  937.  
  938.             (void) mvprintw(SCR_PROMPT_Y, SCR_PROMPT_X,
  939.                 "cycletime = %d seconds", cycletime);
  940.             (void) clrtoeol();
  941.             (void) refresh();
  942.         }
  943.  
  944.         break;
  945.     case '+':            /* increase cycletime        */
  946.         reset_prevshowwhich = 0;
  947.         cycletime += CYCLETIME;
  948.  
  949.         (void) getitimer(ITIMER_REAL, &itv);
  950.  
  951.         itv.it_interval.tv_sec = cycletime;
  952.         itv.it_interval.tv_usec = 0;
  953.  
  954.         (void) setitimer(ITIMER_REAL, &itv, (struct itimerval *) 0);
  955.  
  956.         (void) mvprintw(SCR_PROMPT_Y, SCR_PROMPT_X,
  957.             "cycletime = %d seconds", cycletime);
  958.         (void) clrtoeol();
  959.         (void) refresh();
  960.         break;
  961.     case '-':            /* decrease cycletime        */
  962.         reset_prevshowwhich = 0;
  963.         if (cycletime > CYCLETIME) {
  964.             cycletime -= CYCLETIME;
  965.  
  966.             (void) getitimer(ITIMER_REAL, &itv);
  967.  
  968.             itv.it_interval.tv_sec = cycletime;
  969.             itv.it_interval.tv_usec = 0;
  970.  
  971.             (void) setitimer(ITIMER_REAL, &itv,
  972.                 (struct itimerval *) 0);
  973.  
  974.             (void) mvprintw(SCR_PROMPT_Y, SCR_PROMPT_X,
  975.                 "cycletime = %d seconds", cycletime);
  976.             (void) clrtoeol();
  977.             (void) refresh();
  978.         }
  979.  
  980.         break;
  981.     case '=':            /* reset cycletime        */
  982.         reset_prevshowwhich = 0;
  983.         cycletime = CYCLETIME;
  984.  
  985.         (void) getitimer(ITIMER_REAL, &itv);
  986.  
  987.         itv.it_interval.tv_sec = cycletime;
  988.         itv.it_interval.tv_usec = 0;
  989.  
  990.         (void) setitimer(ITIMER_REAL, &itv, (struct itimerval *) 0);
  991.  
  992.         (void) mvprintw(SCR_PROMPT_Y, SCR_PROMPT_X,
  993.             "cycletime reset to %d seconds", cycletime);
  994.         (void) clrtoeol();
  995.         (void) refresh();
  996.         break;
  997.     case ']':            /* scroll forward        */
  998.         reset_prevshowwhich = 0;
  999.         {
  1000.             int slim;
  1001.             if (scroll_limit[showwhich] == NULL)
  1002.             break;
  1003.             slim = *(scroll_limit[showwhich]);
  1004.             if (slim <= NFSLINES)
  1005.             break;
  1006.             scroll_off[showwhich] += NFSLINES - 2;
  1007.             if (scroll_off[showwhich] > (slim - NFSLINES)) {
  1008.             scroll_off[showwhich] = (slim - NFSLINES);
  1009.             }
  1010.         }
  1011.  
  1012.         (void) clrtoeol();
  1013.         label_screen();
  1014.         update_screen();
  1015.         (void) refresh();
  1016.  
  1017.         break;
  1018.     case '[':            /* scroll back            */
  1019.         reset_prevshowwhich = 0;
  1020.         scroll_off[showwhich] -= NFSLINES - 2;
  1021.         if (scroll_off[showwhich] < 0)
  1022.             scroll_off[showwhich] = 0;
  1023.  
  1024.         (void) clrtoeol();
  1025.         label_screen();
  1026.         update_screen();
  1027.         (void) refresh();
  1028.  
  1029.         break;
  1030.     case ' ':            /* resume after help */
  1031.         if (prev_showwhich > 0) {
  1032.             showwhich = prev_showwhich;
  1033.             label_screen();
  1034.             update_screen();
  1035.             (void) refresh();
  1036.             break;
  1037.         }
  1038.         /* not set?  drops through to "default" */
  1039.     default:            /* give them some help        */
  1040.         reset_prevshowwhich = 0;
  1041.  
  1042.         if (showwhich != SHOWHELP)    /* save current display mode */
  1043.             prev_showwhich = showwhich;
  1044.  
  1045.         showwhich = SHOWHELP;
  1046.         
  1047.         label_screen();
  1048.         (void) refresh();
  1049.  
  1050.         break;
  1051.     }
  1052.  
  1053.     if (reset_prevshowwhich)
  1054.         prev_showwhich = 0;
  1055. }
  1056.